package pokemon;

import java.util.ArrayList;
import java.util.HashMap;


public class Synergizer
{
	private static final int RESISTX2_WEAKX2_SCORE = 10;
	private static final int RESISTX4_WEAKX2_SCORE = 15;
	private static final int IMMUNE_WEAKX2_SCORE = 20;
	private static final int RESISTX2_WEAKX4_SCORE = 20;
	private static final int RESISTX4_WEAKX4_SCORE = 25;
	private static final int IMMUNE_WEAKX4_SCORE = 30;
	
	private Pokemon poke;
	private Pokedex dex;
	private HashMap<Integer, ArrayList<Pokemon>> partners = new HashMap<Integer, ArrayList<Pokemon>>();
	
	public Synergizer(Pokemon poke, Pokedex dex)
	{
		this.poke = poke;
		this.dex = dex;
		synergize();
	}
	
	//Ranking
	//			immune quad double
	//	my quad   30	25  20    
	//	my double 20    15	10
	//
	private void synergize()
	{
		int synergyScore;
		for(Pokemon partner : dex)
		{
			synergyScore = 0;
			synergyScore += oneWaySynergize(poke, partner);
			synergyScore += oneWaySynergize(partner, poke);
			synergyScore /= 2;
			
			ArrayList<Pokemon> temp;
			if(partners.get(synergyScore) == null)
			{
				temp = new ArrayList<Pokemon>();
				temp.add(partner);
				partners.put((Integer) synergyScore, temp);
			}
			else
			{
				temp = partners.get((Integer) synergyScore);
				temp.add(partner);
				partners.remove((Integer) synergyScore);
				partners.put(synergyScore, temp);
			}
		}
	}
	public ArrayList<Pokemon> getList(Pokemon p)
	{
		HashMap<Integer, ArrayList<Pokemon>> partnersTeam = new HashMap<Integer, ArrayList<Pokemon>>();
		int synergyScore = 0;
		for(Pokemon partner : dex)
		{ 
			synergyScore = 0;
			//System.out.println(seedPokemon.get(seedPokemon.indexOf(nextPartner)));
			synergyScore += oneWaySynergize(p, partner);
			ArrayList<Pokemon> temp;
			if(partnersTeam.get(synergyScore) == null)
			{
				temp = new ArrayList<Pokemon>();
				temp.add(partner);
				partnersTeam.put((Integer) synergyScore, temp);
			}
			else
			{
				temp = partnersTeam.get((Integer) synergyScore);
				temp.add(partner);
				partnersTeam.remove((Integer) synergyScore);
				partnersTeam.put(synergyScore, temp);
			}
		}
		int maxValue = 0;
		for(int value : partnersTeam.keySet())
		{
			if(value > maxValue)
			{
				maxValue = value;
			}
		}
		return partnersTeam.get((Integer) maxValue);
	}
//	public ArrayList<Pokemon> synergyOfThree(Pokemon pokeOne, Pokemon pokeTwo, Pokemon pokeThree)
//	{		
//		HashMap<Integer, ArrayList<Pokemon>> partnersTeam = new HashMap<Integer, ArrayList<Pokemon>>();
//		int synergyScore = 0;
//		for(Pokemon partner : dex)
//		{ 
//			synergyScore = 0;
//			//System.out.println(seedPokemon.get(seedPokemon.indexOf(nextPartner)));
//			synergyScore += oneWaySynergize(p, partner);
//			ArrayList<Pokemon> temp;
//			if(partnersTeam.get(synergyScore) == null)
//			{
//				temp = new ArrayList<Pokemon>();
//				temp.add(partner);
//				partnersTeam.put((Integer) synergyScore, temp);
//			}
//			else
//			{
//				temp = partnersTeam.get((Integer) synergyScore);
//				temp.add(partner);
//				partnersTeam.remove((Integer) synergyScore);
//				partnersTeam.put(synergyScore, temp);
//			}
//		}
//		int maxValue = 0;
//		for(int value : partnersTeam.keySet())
//		{
//			if(value > maxValue)
//			{
//				maxValue = value;
//			}
//		}
//		return partnersTeam.get((Integer) maxValue);
//	}
//	private double calcSynergyOfThree(Pokemon pokeOne, Pokemon pokeTwo, Pokemon pokeThree)
//	{
//		int synergyScore = 0;
//		int weaknessTotal=p.getWeaknessesX2().size()+p.getWeaknessesX4().size()*2;
//		double percentPer=100.0/weaknessTotal;
//		ArrayList<Types> weaknesses = new ArrayList<Types>(p.getWeaknessesX4());
//		for(Types weakness:weaknesses)
//		{
//			if(partner.getImmunities().contains(weakness))
//			{
//				synergyScore += percentPer*1.5*2;
//				//synergyScore += IMMUNE_WEAKX4_SCORE;
//			}
//			else if(partner.getResistancesX4().contains(weakness))
//			{
//				synergyScore += percentPer*1.25*2;
//				//synergyScore += RESISTX4_WEAKX4_SCORE;
//			}
//			else if(partner.getResistancesX2().contains(weakness))
//			{
//				synergyScore += percentPer*1*2;
//				//synergyScore += RESISTX2_WEAKX4_SCORE;
//			}
//		}
//		weaknesses = new ArrayList<Types>(p.getWeaknessesX2());
//		for(Types weakness:weaknesses)
//		{
//			if(partner.getImmunities().contains(weakness))
//			{
//				synergyScore += percentPer*1.5*1;
//				//synergyScore += IMMUNE_WEAKX4_SCORE;
//			}
//			else if(partner.getResistancesX4().contains(weakness))
//			{
//				synergyScore += percentPer*1.25*1;
//				//synergyScore += RESISTX4_WEAKX4_SCORE;
//			}
//			else if(partner.getResistancesX2().contains(weakness))
//			{
//				synergyScore += percentPer*1*1;
//				//synergyScore += RESISTX2_WEAKX4_SCORE;
//			}	
//		}
//		//Resisting neutral hits a +, weak is a -.
//		
//		
//		return synergyScore;
//	}
	public ArrayList<Pokemon[]> createTeam()
	{
		HashMap<Integer, ArrayList<Pokemon>> partnersTeam = new HashMap<Integer, ArrayList<Pokemon>>();
		ArrayList<Pokemon[]> seedPokemon = new ArrayList<Pokemon[]>();
		ArrayList<Pokemon[]> tempList = new ArrayList<Pokemon[]>();
		Pokemon[] theStart = new Pokemon[6];
		theStart[0]=poke;
		seedPokemon.add(theStart);
		int index=0;
		while(index<5)
		{
			for(Pokemon[] pokeArray:seedPokemon)
			{
				ArrayList<Pokemon> resultingList = getList(pokeArray[index]);
				for(Pokemon p: resultingList)
				{
					Pokemon[] newList = new Pokemon[6];
					for( int i=0;i<6;i++)
					{
						newList[i]=pokeArray[i];
					}
					newList[index+1]=p;
					tempList.add(newList);
				}
			}
			seedPokemon.clear();
			seedPokemon.addAll(tempList);
			tempList.clear();
			index++;
		}
		return seedPokemon;
	}
	public ArrayList<Pokemon[]> createTeamGivenTwo(Pokemon pokeOne, Pokemon pokeTwo)
	{
		HashMap<Integer, ArrayList<Pokemon>> partnersTeam = new HashMap<Integer, ArrayList<Pokemon>>();
		ArrayList<Pokemon[]> seedPokemon = new ArrayList<Pokemon[]>();
		ArrayList<Pokemon[]> tempList = new ArrayList<Pokemon[]>();
		Pokemon[] theStart = new Pokemon[6];
		theStart[0]=pokeOne;
		theStart[1]=pokeTwo;
		seedPokemon.add(theStart);
		int index=1;
		while(index<5)
		{
			for(Pokemon[] pokeArray:seedPokemon)
			{
				ArrayList<Pokemon> resultingList = getList(pokeArray[index]);
				for(Pokemon p: resultingList)
				{
					Pokemon[] newList = new Pokemon[6];
					for( int i=0;i<6;i++)
					{
						newList[i]=pokeArray[i];
					}
					newList[index+1]=p;
					tempList.add(newList);
				}
			}
			seedPokemon.clear();
			seedPokemon.addAll(tempList);
			tempList.clear();
			index++;
		}
		return seedPokemon;
	}
	public int oneWaySynergize(Pokemon p, Pokemon partner)
	{
		int synergyScore = 0;
		int weaknessTotal=p.getWeaknessesX2().size()+p.getWeaknessesX4().size()*2;
		double percentPer=100.0/weaknessTotal;
		ArrayList<Types> weaknesses = new ArrayList<Types>(p.getWeaknessesX4());
		for(Types weakness:weaknesses)
		{
			if(partner.getImmunities().contains(weakness))
			{
				synergyScore += percentPer*1.5*2;
				//synergyScore += IMMUNE_WEAKX4_SCORE;
			}
			else if(partner.getResistancesX4().contains(weakness))
			{
				synergyScore += percentPer*1.25*2;
				//synergyScore += RESISTX4_WEAKX4_SCORE;
			}
			else if(partner.getResistancesX2().contains(weakness))
			{
				synergyScore += percentPer*1*2;
				//synergyScore += RESISTX2_WEAKX4_SCORE;
			}
		}
		weaknesses = new ArrayList<Types>(p.getWeaknessesX2());
		for(Types weakness:weaknesses)
		{
			if(partner.getImmunities().contains(weakness))
			{
				synergyScore += percentPer*1.5*1;
				//synergyScore += IMMUNE_WEAKX4_SCORE;
			}
			else if(partner.getResistancesX4().contains(weakness))
			{
				synergyScore += percentPer*1.25*1;
				//synergyScore += RESISTX4_WEAKX4_SCORE;
			}
			else if(partner.getResistancesX2().contains(weakness))
			{
				synergyScore += percentPer*1*1;
				//synergyScore += RESISTX2_WEAKX4_SCORE;
			}	
		}
		//Resisting neutral hits a +, weak is a -.
		return synergyScore;
	}
	
	public ArrayList<Pokemon> getPartners()
	{
		int maxValue = 0;
		for(int value : partners.keySet())
		{
			if(value > maxValue)
			{
				maxValue = value;
			}
		}
		return partners.get((Integer) maxValue);
	}
}
